package util.core.plugins.mycraft.cc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.craftbukkit.libs.jline.internal.Log;
import entity.core.plugins.mycraft.cc.file;
import implate.core.plugins.mycraft.cc.FileOperImplate;
import implate.core.plugins.mycraft.cc.Mycraft;

/**
 * 文件操作类 用以文件读写, 移动, 复制, 删除
 * 
 * @author delovt
 * 
 */
public class FileOper  extends Mycraft implements FileOperImplate {
    private String url     = "";
    private File   f       = null;
    private int    line    = 0;
    public boolean hasNext = false; // 文件读取末尾标志
    public file    fs      = null;
    private boolean Safe = false;

    public FileOper(String u) throws FileNotFoundException {
        if (u.length() > 2) {
            this.url = u;
            SplitFile(url);
        } else
            Log.warn("参数错误: ", u);
    }

    public FileOper() {
        if (this.url.isEmpty() || this.url == null)
            Log.warn("参数错误: ", this.url);
        else
            SplitFile(this.url);
    }

    /**
     * 读取指定行
     * 
     * @param n
     *            指定读取的行号
     * @return 行内容
     */
    public String Fetch(int n) {
        if (this.f != null) {
            try {
                if (this.f.canRead()) {
                    int totalLines = 0; // 记录文件总行数
                    FileReader fileReader = new FileReader(this.f);
                    LineNumberReader reader = new LineNumberReader(fileReader);
                    String result = "";
                    int lines = 0;
                    while (result != null) {
                        lines++;
                        totalLines++;
                        result = reader.readLine();
                        if (lines == n) {
                            if (result == null) {
                                Log.error("该行内容为空:", this.f.getName() + ": line = " + n);
                            }
                            reader.close();
                            fileReader.close();
                            return result;
                        }
                    }
                    reader.close();
                    fileReader.close();
                    if (totalLines < n) {
                        Log.error("该行不存在:", this.f.getName() + ": line = " + n);
                        return null;
                    }
                } else
                    Log.error("文件不可读: ", this.fs.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 读取指定范围行数的内容
     * 
     * @param start
     *            开始
     * @param end
     *            结束
     * @return 行内容集
     */
    public List<String> FetchRange(int start, int end) {
        if (this.f != null) {
            try {
                if (this.f.canRead()) {
                    int totalLines = 0; // 记录文件总行数
                    FileReader reader = new FileReader(this.f);
                    BufferedReader br = new BufferedReader(reader);
                    String str = "";
                    List<String> result = new ArrayList<String>();
                    int lines = 0;
                    while ((str = br.readLine()) != null) {
                        lines++;
                        totalLines++;
                        if (lines >= start && lines <= end) {
                            result.add(str);
                        }
                    }
                    reader.close();
                    br.close();
                    if (totalLines < start) {
                        Log.error("此范围内容不存在:", this.f.getName() + ": startLine = " + start + " endLine = " + end);
                        return null;
                    } else {
                        return result;
                    }
                } else
                    Log.error("文件不可读: ", this.fs.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 从开头起, 每次读取一行, 游标保存在 line 中
     * 
     * @return 行内容
     */
    public String FetchNext() {
        if (this.f != null) {
            try {
                if (this.f.canRead()) {
                    FileReader fileReader = new FileReader(this.f);
                    LineNumberReader reader = new LineNumberReader(fileReader);
                    String result = "";
                    String firstLine = "";
                    int lines = 0;
                    int totalLines = 0;
                    while (result != null) {
                        result = reader.readLine();
                        if (lines == 0) {
                            firstLine = result;
                        }
                        if (lines == this.line) {
                            if (result == null) {
                                Log.error("该行内容为空:", this.f.getName() + ": line = " + this.line);
                            }
                            this.line = ++lines; // 记录游标
                            totalLines++;
                            reader.close();
                            fileReader.close();
                            return result;
                        }
                        lines++;
                        totalLines++;
                    }
                    reader.close();
                    fileReader.close();
                    if (this.line > totalLines) {
                        Log.error("读取游标已经到文件末尾:", this.f.getName() + ": line = " + this.line);
                        this.line = 1;
                        return firstLine;// 返回首行内容,line默认从0开始，所以游标赋值1，表示下次读取第二行
                    }
                } else
                    Log.error("文件不可读: ", this.fs.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 在指定行处插入新行
     * 
     * @param n
     *            行号
     * @param data
     *            行内容
     * @return 写入状态
     */
    public boolean WriteLine(int n, String data) {
        // 读取文件内容进行缓存
        try {
            FileReader reader = new FileReader(this.f);
            BufferedReader br = new BufferedReader(reader);
            String str = "";
            StringBuffer inputData = new StringBuffer(str);
            int lines = 0;
            while ((str = br.readLine()) != null) {
                if (lines == n) {
                    inputData.append(data + "\r\n");
                }
                inputData.append(str + "\r\n");
                lines++;
            }
            reader.close();
            br.close();
            // 将缓存中的内容重新写入文件
            FileOutputStream out = new FileOutputStream(this.f);
            out.write(inputData.toString().getBytes());
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.error("写入出错: ", e.toString());
        }
        return false;
    }

    /**
     * 写入新的内容覆盖掉当前文件
     * 
     * @param data
     *            需要写入的数据
     * @return 写入状态
     */
    public boolean WriteAll(List<String> data) {
        StringBuffer inputData = new StringBuffer("");
        if (data == null) {
            Log.error("写入内容为空: ", data);
            return false;
        }
        for (int i = 0; i < data.size(); i++) {
            inputData.append(data.get(i) + "\r\n");
        }
        try {
            FileOutputStream out = new FileOutputStream(this.f);
            out.write(inputData.toString().getBytes());
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.error("写入出错: ", e.toString());
        }
        return false;
    }

    /**
     * 移动当前文件至目标路径
     * 
     * @param path
     * @return
     */
    public boolean MoveTo(String path) {
        boolean result = CopyTo(path);
        if (result == true) {
            result = Delete();
            if (result == true) {
                return true;
            } else {
                Log.error("文件成功复制到指定路径，但是原文件删除失败", this.f.getName());
                return false;
            }
        }
        Log.error("文件移动失败", this.f.getName());
        return false;
    }

    /**
     * 复制当前文件至目标路径
     * 
     * @param path
     * @return
     */
    public boolean CopyTo(String path) {
        File newFilePath = new File(path);
        if (!newFilePath.isDirectory()) {
            Log.error("复制路径有误: ", path);
        }
        try {
            int byteread = 0;
            if (this.f.exists()) { // 文件存在时
                path = path + this.f.getName();
                InputStream inStream = new FileInputStream(this.f); // 读入原文件
                FileOutputStream fs = new FileOutputStream(path);
                byte[] buffer = new byte[1024];
                while ((byteread = inStream.read(buffer)) != -1) {
                    fs.write(buffer, 0, byteread);
                }
                fs.flush();
                inStream.close();
                fs.close();
                return true;
            }
        } catch (Exception e) {
            Log.error("复制文件有误", e.toString());

        }
        return false;
    }

    /**
     * 删除当前文件
     * 
     * @return
     */
    public boolean Delete() {
        if (this.f.exists()) {
            f.delete();
            return true;
        } else {
            Log.error("当前文件不存在:", this.f.getName());
        }
        return false;
    }

    @Override
    public void SplitFile(String filename) {
        // TODO Auto-generated method stub
        String tmp = filename.substring(0, 2);
        if (tmp.equals("./")) {
            filename = new File("").getAbsolutePath() + "/" + filename.substring(2);
        }
        this.f = new File(filename);
        if (f.exists()) {
            if (fs == null)
                fs = new file();
            this.fs.setName(f.getName());
            this.fs.setPath(f.getPath());
            String tmp0[] = filename.split("\\.");
            if (tmp0.length < 1) {
                this.fs.setSuffix("null");
            } else {
                this.fs.setSuffix(tmp0[tmp0.length - 1]);
            }
            this.setSafe(true);
        } else {
            this.f = null;
            Log.error("[!] File is not exists => " + filename);
        }
    }

    @Override
    public String GetFilePath() {
        // TODO Auto-generated method stub
        if (fs != null) {
            return this.fs.getPath();
        }
        return null;
    }

    @Override
    public String GetFileName() {
        // TODO Auto-generated method stub
        if (fs != null) {
            return this.fs.getName();
        }
        return null;
    }

    @Override
    public String GetFileSuffix() {
        // TODO Auto-generated method stub
        if (fs != null) {
            return this.fs.getSuffix();
        }
        return null;
    }

    @Override
    public <T> Object FileData() {
        // TODO Auto-generated method stub
        return null;
    }

    public int getLine() {
        return line;
    }

    public void setLine(int line) {
        this.line = line;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

	public boolean isSafe() {
		return Safe;
	}

	public void setSafe(boolean safe) {
		Safe = safe;
	}
}
